<template>
  <!--过渡动画-->
  <!--路由出口-->
  <router-view v-slot="{Component}">
    <!--动画-->
    <transition :name="transitionName" @before-enter="beforeEnter"
                @after-leave="afterLeave">
      <keep-alive :include="virtualTaskStack">
        <component :class="{'fixed left-0 top-0 w-screen z-50':isAnimation}" :is="Component"
                   :key="$route.fullPath"></component>
      </keep-alive>
    </transition>
  </router-view>
  <!--组件缓存-->
</template>

<script>
const NONE = 'none'
const ROUTER_TYPE_PUSH = 'push'
const ROUTER_TYPE_BACK = 'back'

const ROUTER_TYPE_ENUM = [NONE, ROUTER_TYPE_PUSH, ROUTER_TYPE_BACK]
</script>
<script setup>
import {useRouter} from "vue-router";
import {ref} from "vue";

const props = defineProps({
  //路由的跳转类型,进入或是退出组件
  routerType: {
    type: String,
    default: NONE,
    validator(value) {
      //2.开发者指定的风格在可选项中
      const result = ROUTER_TYPE_ENUM.includes(value)
      if (!result) {
        throw new Error(`您的routerType必须是${ROUTER_TYPE_ENUM.join('、')}中的一个`)
      }
      return result
    }
  },
  //首页组件名称
  mainComponent: {
    type: String,
    required: true
  }
})
const router = useRouter()
//跳转动画
const transitionName = ref('')

/**
 * router的前置守卫
 */
router.beforeEach((to, form) => {
  //定义当前动画名称
  transitionName.value = props.routerType
  if (props.routerType === ROUTER_TYPE_PUSH) {
    //入栈
    virtualTaskStack.value.push(to.name)
  } else if (props.routerType === ROUTER_TYPE_BACK) {
    //出栈
    virtualTaskStack.value.pop()
  }
  //进入首页,默认清空栈
  if (to.name === props.mainComponent) {
    clearStack()
  }
})
//处理动画状态
const isAnimation = ref(false)
const beforeEnter = () => {
  isAnimation.value = true
}
const afterLeave = () => {
  isAnimation.value = false
}

//虚拟任务栈的数组，用它来表示栈操作
const virtualTaskStack = ref([props.mainComponent])
/**
 *清空栈
 */
const clearStack = () => {
  virtualTaskStack.value = [props.mainComponent]
}
</script>

<style lang="scss" scoped>
// push页面时：新页面的进入动画
.push-enter-active {
  animation-name: push-in;
  animation-duration: 0.4s;
}

// push页面时：老页面的退出动画
.push-leave-active {
  animation-name: push-out;
  animation-duration: 0.4s;
}

// push页面时：新页面的进入动画
@keyframes push-in {
  0% {
    transform: translate(100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

// push页面时：老页面的退出动画
@keyframes push-out {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-50%, 0);
  }
}

// 后退页面时：即将展示的页面动画
.back-enter-active {
  animation-name: back-in;
  animation-duration: 0.4s;
}

// 后退页面时：后退的页面执行的动画
.back-leave-active {
  animation-name: back-out;
  animation-duration: 0.4s;
}

// 后退页面时：即将展示的页面动画
@keyframes back-in {
  0% {
    width: 100%;
    transform: translate(-100%, 0);
  }
  100% {
    width: 100%;
    transform: translate(0, 0);
  }
}

// 后退页面时：后退的页面执行的动画
@keyframes back-out {
  0% {
    width: 100%;
    transform: translate(0, 0);
  }
  100% {
    width: 100%;
    transform: translate(50%, 0);
  }
}
</style>
